package com.camelot.ccr.global.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;
/**
 * @author liujun
 * Description:拷贝、复制bean属性--扩展spring BeanUtils功能，解决把空属性也拷贝进来的问题
 * Apr 12, 2012
 */
public abstract class BeanUtils extends org.springframework.beans.BeanUtils {
	private static Log logger = LogFactory.getLog(BeanUtils.class);// logger日志
	/**
	 * <pre>
	 * 拷贝一个对象里非空属性值到另一个对象
	 * </pre>
	 * @param source 源对象
	 * @param target 目标对象
	 * @author Liu Jun, 2013-12-27 上午10:01:42
	 */
	public static void copyProperties(Object source, Object target) {   
	    Assert.notNull(source, "Source must not be null");   
	    Assert.notNull(target, "Target must not be null");   
	    Class<?> actualEditable = target.getClass();   
	    PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);   
	    for (PropertyDescriptor targetPd : targetPds) { 
	    	if (targetPd.getWriteMethod() != null) {
	    		PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
	    		if (sourcePd != null && sourcePd.getReadMethod() != null) {
	    			try {
	    				Method readMethod = sourcePd.getReadMethod(); 
	    				if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
	    					readMethod.setAccessible(true);
	    				}
	    				Object value = readMethod.invoke(source);  
	    				// 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等  
	    				if (value != null) { 
	    					Method writeMethod = targetPd.getWriteMethod();
	    					if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { 
	    						writeMethod.setAccessible(true);
	    					}
	    					writeMethod.invoke(target, value);
	    				}
	    			}catch (Throwable ex) {
	    				logger.error(source.getClass().getName()+"属性拷贝到"+target.getClass().getName()+"中失败", ex);
	    	            throw new FatalBeanException("Could not copy properties from source to target", ex);  
	    			}
	    		}
	    	}
	    }
	}
}
